﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;

namespace Commands
{
    static class Extensions
    {
        /// <summary>
        /// Replace last occurrence of the string.
        /// </summary>
        /// <param name="str">String, in which occurrence will be replaced.</param>
        /// <param name="find">String to find.</param>
        /// <param name="replace">Replacing string.</param>
        /// <returns></returns>
        public static string ReplaceLastOccurrence(this string str, string find, string replace)
        {
            int place = str.LastIndexOf(find);
            string result = str.Remove(place, find.Length).Insert(place, replace);
            return result;
        }

        /// <summary>
        /// Trim a matching pair of quotes from the start and end of a string. 
        /// It will only trim one character from each end, and it will not trim from just one end.
        /// </summary>
        public static string TrimMatchingQuotes(this string input, char quote)
        {
            if ((input.Length >= 2) &&
                (input[0] == quote) && (input[input.Length - 1] == quote))
                return input.Substring(1, input.Length - 2);

            return input;
        }

        /// <summary>
        /// Split that takes a function that has to decide whether 
        /// the specified character should split the string:
        /// </summary>
        /// <remarks>
        /// http://stackoverflow.com/questions/298830/split-string-containing-command-line-parameters-into-string-in-c-sharp
        /// </remarks>
        public static IEnumerable<string> Split(this string str, Func<char, bool> controller)
        {
            int nextPiece = 0;

            for (int c = 0; c < str.Length; c++)
            {
                if (controller(str[c]))
                {
                    yield return str.Substring(nextPiece, c - nextPiece);
                    nextPiece = c + 1;
                }
            }

            yield return str.Substring(nextPiece);
        }

        public static bool IsUnique<T>(this IEnumerable<T> collection, Func<T, IEnumerable<string>> selector)
        {
            var allValues = collection.SelectMany(selector);

            return allValues.Count() == allValues.Distinct().Count();
        }

        public static bool IsUnique<T>(this IEnumerable<T> list)
        {
            var hs = new HashSet<T>();
            return list.All(hs.Add);
        }

        public static ParameterAttribute GetParameterAttribute(this ParameterInfo parameterInfo)
        {
            object[] attributes = parameterInfo.GetCustomAttributes(typeof(ParameterAttribute), true);

            Debug.Assert(attributes != null);

            return attributes.FirstOrDefault() as ParameterAttribute;
        }
    }
}
